package aceim.app.service; import java.util.concurrent.Executors; import aceim.api.dataentity.ItemAction; import aceim.api.service.ICoreProtocolCallback; import aceim.api.service.ICoreProtocolCallback.Stub; import aceim.api.service.IProtocolService; import aceim.api.utils.Logger; import aceim.app.AceImException; import aceim.app.dataentity.ProtocolResources; import aceim.app.service.ProtocolServicesManager.ProtocolListener; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.os.IBinder; import android.os.RemoteException; public class ProtocolService implements ServiceConnection { private Context mContext; private volatile boolean exiting = false; private final String packageName; private final String className; private ProtocolResources resources; private final ICoreProtocolCallback callback; private final ProtocolListener mProtocolListener; private IProtocolService protocol; private ProtocolService(Context context, String packageName, String className, ICoreProtocolCallback callback, ProtocolListener protocolListener) { this.packageName = packageName; this.className = className; this.callback = callback; this.mContext = context; this.mProtocolListener = protocolListener; } private void bind() { Intent intent = new Intent(); intent.setClassName(packageName, className); Logger.log("binding: "+intent ); mContext.startService(intent); boolean d = mContext.getApplicationContext().bindService(intent, this, 0); Logger.log(d ? "Binded" : "Not binded"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { protocol = IProtocolService.Stub.asInterface(service); try { protocol.registerCallback(callback); fillResources(); mProtocolListener.onAction(this, ItemAction.JOINED); } catch (RemoteException e) { Logger.log(e); } } @Override public void onServiceDisconnected(ComponentName name) { protocol = null; if (!exiting) { Executors.defaultThreadFactory().newThread(mRebindProtocolsRunnable).start(); mProtocolListener.onAction(this, ItemAction.LEFT); } } private void fillResources() throws RemoteException { this.resources = new ProtocolResources(this); } private ProtocolResources getFullProtocolResources() { ProtocolResources out = new ProtocolResources(this); out.setProtocolVersion(fillInfoField("version", packageName)); out.setApiVersion(fillInfoField("api_version", packageName)); return out; } private String fillInfoField(String idName, String packageName){ Resources r; try { r = resources.getNativeResourcesForProtocol(null); } catch (AceImException e) { Logger.log(e); return null; } int id = r.getIdentifier(idName, "string", packageName); if (id != 0){ return r.getString(id); } else { return null; } } public Context getContext() { return mContext; } public String getProtocolServicePackageName() { return packageName; } public ProtocolResources getResources(boolean getProtocolInfo) { if (getProtocolInfo) { return getFullProtocolResources(); } return resources; } public ICoreProtocolCallback getCallback() { return callback; } public IProtocolService getProtocol() { return protocol; } public static ProtocolService create(Context context, String packageName, String className, Stub protocolCallback, ProtocolListener protocolListener) { ProtocolService ps = new ProtocolService(context, packageName, className, protocolCallback, protocolListener); ps.bind(); while (ps.getProtocol() == null) { try { Thread.sleep(250); } catch (InterruptedException e) {} } return ps; } public ServiceInfo getServiceInfo() { try { return mContext.getPackageManager().getServiceInfo(new ComponentName(packageName, className), PackageManager.GET_RESOLVED_FILTER); } catch (NameNotFoundException e) { Logger.log(e); return null; } } /** * @return the className */ public String getServiceClassName() { return className; } public void onExit() { exiting = true; try { getProtocol().shutdown(); } catch (RemoteException e) {} } private final Runnable mRebindProtocolsRunnable = new Runnable() { @Override public void run() { bind(); } }; }